/**
 * 
 */
package com.sip.scanadapter.domainparsers;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.namespace.QName;

import com.sip.dbadapter.dao.domain.ApiDefinition;
import com.sip.dbadapter.dao.domain.ConsumeType;
import com.sip.dbadapter.dao.domain.MediaType;
import com.sip.dbadapter.dao.domain.ProduceType;
import com.sip.dbadapter.dao.domain.ScanTypeRest;
import com.sip.scanadapter.common.StratergyType;
import com.sun.research.ws.wadl.Application;
import com.sun.research.ws.wadl.Method;
import com.sun.research.ws.wadl.Param;
import com.sun.research.ws.wadl.Representation;
import com.sun.research.ws.wadl.Resource;
import com.sun.research.ws.wadl.Resources;
import com.sun.research.ws.wadl.Response;

/**
 * @author Dhanushka Ariyasingha.
 * 
 */
public class ScanTypeParser implements Parser<Map<String, ScanTypeRest>, Application> {

	private Map<String, ScanTypeRest> scanTypeObjCollection = null;

	private StringBuilder urlBuilderServicePath = new StringBuilder();

	private StringBuilder urlBuilderServiceMethod = new StringBuilder();

	private String baseUrl;

	public ScanTypeParser() {
		scanTypeObjCollection = new HashMap<String, ScanTypeRest>();
	}

	public Map<String, ScanTypeRest> parser(Application application) {

		final List<Resources> resourceList = application.getResources();
		collectServiceComponent(resourceList);

		return scanTypeObjCollection;
	}

	private void collectServiceComponent(final List<Resources> resourceList) {

		for (final Resources resources : resourceList) {

			String baseUrl = resources.getBase();
			System.out.println("BaseUrl:" + baseUrl);

			baseUrl = (baseUrl.substring(baseUrl.length() - 1).equals("/")) ? baseUrl.substring(0, baseUrl.length() - 1)
					: baseUrl;
			this.baseUrl = baseUrl;

			final List<Resource> subResourceList = resources.getResource();

			collectServiceInfo(subResourceList);
		}

	}

	private void collectServiceInfo(final List<Resource> subResourceList) {

		for (final Resource resource : subResourceList) {

			final String resourcePath = resource.getPath();
			System.out.println("Service Path:" + resourcePath);

			urlBuilderServicePath.append(resourcePath);

			collectServiceMethodInfo(resource);

			urlBuilderServicePath.delete(0, urlBuilderServicePath.length());
		}
	}

	private void collectServiceMethodInfo(final Resource resource) {

		final List<Object> methodOrResourceList1 = resource.getMethodOrResource();

		for (Object object : methodOrResourceList1) {

			if (object instanceof Resource) {

				final Resource serviceResource = (Resource) object;

				collectServiceMethodDefinitionInfo(serviceResource);

			} else if (object instanceof Method) {

				final String serviceMethod = resource.getPath(); 

				final Method method = (Method) object;
				final ScanTypeRest scanTypeDomain = new ScanTypeRest();
				
				scanTypeDomain.setMethodAction(method.getName());

				final Set<MediaType> mediaTypeSet = new HashSet<MediaType>();		
				collectMediaTypeInfo(method, mediaTypeSet);

				scanTypeDomain.setMethodUrl(baseUrl + "/" +serviceMethod);
				scanTypeDomain.setMediaTypeSet(mediaTypeSet);
				scanTypeDomain.setResourceBase(baseUrl);

				scanTypeObjCollection.put(urlBuilderServicePath.toString() + urlBuilderServiceMethod.toString() +"/" + method.getId(), scanTypeDomain);

			}
		}
	}

	private void collectServiceMethodDefinitionInfo(final Resource serviceResource) {

		final List<Object> methodOrResourceList2 = serviceResource.getMethodOrResource();
		System.out.println("Service Method:" + serviceResource.getPath());
		
		String serviceMethod = serviceResource.getPath();
		serviceMethod = serviceMethod.substring(0,1).equals("/") ? serviceMethod : "/" + serviceMethod; 
		
		urlBuilderServiceMethod.append(serviceMethod);

		for (Object methodObj : methodOrResourceList2) {

			if (methodObj instanceof Method) {

				final Method method = (Method) methodObj;
				collectMethodInfo(method);

			}

		}

		urlBuilderServiceMethod.delete(0, urlBuilderServiceMethod.length());
	}

	private void collectMethodInfo(final Method method) {

		final ScanTypeRest scanTypeDomain = new ScanTypeRest();
		scanTypeDomain.setMethodAction(method.getName());

		final Set<MediaType> mediaTypeSet = new HashSet<MediaType>();		
		collectMediaTypeInfo(method, mediaTypeSet);
		
		final String servicePath  = urlBuilderServicePath.substring(0, 1).contains("/") ?  urlBuilderServicePath.toString() : "/" + urlBuilderServicePath.toString();

		scanTypeDomain.setMethodUrl(baseUrl + servicePath + urlBuilderServiceMethod.toString());
		scanTypeDomain.setMediaTypeSet(mediaTypeSet);
		scanTypeDomain.setResourceBase(baseUrl);

		scanTypeObjCollection.put(urlBuilderServicePath.toString() + urlBuilderServiceMethod.toString() + "/" + method.getId(), scanTypeDomain);
	}

	private void collectMediaTypeInfo(final Method method, final Set<MediaType> mediaTypeSet) {
		
		MediaType mediaTypeDomainObj = null;

		final List<Response> responseList = method.getResponse();
		for (final Response response : responseList) {

			final List<Representation> representationList = response.getRepresentation();

			for (final Representation representation : representationList) {

				mediaTypeDomainObj = new MediaType();

				final String mediaType = representation.getMediaType();
				final QName element = representation.getElement();

				System.out.println("    Media Type:" + mediaType);
				System.out.println("    Element Name:" + element);

				mediaTypeDomainObj.setMediaName(mediaType);
				mediaTypeSet.add(mediaTypeDomainObj);
			}
		}
	}

}
